package EventPackage;

import InstrumentationPackage.MessageWindow;

public abstract class Participant {
	protected int subSystemHaltEnvId;
	protected String EvtMgrIP = "localhost";		// Event Manager IP address
	protected EventManagerInterface em = null;		// Interface object to the event manager
	protected EventQueue eq = null;				// Message Queue
	protected Event Evt = null;				// Event object
	protected boolean Done = false;				// Loop termination flag
	protected int	Delay = 2500;				// The loop delay (2.5 seconds)
	protected String name = null;					// Participant's name
	protected boolean registered = true;			// Signifies that this class is registered with an event manager.
	protected MessageWindow mw; 					// Message Window
	protected String mwTitle;
	protected int mwXpos;
	protected int mwYpos;
	protected int mwHeight;
	protected int mwWidth;
        protected static String ACK;	
	
	protected void setParameters(String mwTitle, int mwXpos, int mwYpos, int mwHeight,
			int mwWidth, int subSystemHaltEnvId, String sensor_name) {
		this.mwTitle = mwTitle;
		this.mwXpos = mwXpos;
		this.mwYpos = mwYpos;
		this.mwHeight = mwHeight;
		this.mwWidth = mwWidth;
		this.subSystemHaltEnvId = subSystemHaltEnvId;
                this.ACK = sensor_name;
	}

	public void run (String args[])
	{
		/////////////////////////////////////////////////////////////////////////////////
		// Try to register with the event manager
		/////////////////////////////////////////////////////////////////////////////////

 		em = register(args);

		// Here we check to see if registration worked. If em is null then the
		// event manager interface was not properly created.
		if (em != null)
		{
			// Here we create a message window
			mw = createMessageWindow();
			
			mw.WriteMessage("Registered with the event manager." );

	    	try
	    	{
				mw.WriteMessage("   Participant id: " + em.GetMyId() );
				mw.WriteMessage("   Registration Time: " + em.GetRegistrationTime() );

			} // try
	    	catch (Exception e)
			{
				mw.WriteMessage("Error:: " + e);

			} // catch

			mw.WriteMessage("Beginning Simulation... ");
			
			beforeLooping();

			while ( !Done )
			{
				initialPostPhase();
				
				// Get the message queue
				try
				{
					eq = em.GetEventQueue();

				} // try

				catch( Exception e )
				{
					mw.WriteMessage("Error getting event queue::" + e );

				} // catch

				// If there are messages in the queue, we read through them.

				int qlen = eq.GetSize(); 
				
				for ( int i = 0; i < qlen; i++ )
				{
					Evt = eq.GetEvent();

					// If the event ID == 99 then this is a signal that the simulation
					// is to end. At this point, the loop termination flag is set to
					// true and this process unregisters from the event manager.

                    // This method responds with an ACK to the DevicesController
                    if ( Evt.GetEventId() == 27 ){
                    	postEvent(24, ACK);
                    } // if
					
					if ((Evt.GetEventId() == 99) || (Evt.GetEventId() == subSystemHaltEnvId))
					{

						halt();
					} else {
						
						handlePhase();
						finalPostPhase();
					}

				} // for


				// Here we wait for a 2.5 seconds before we start the next sample

				try
				{
					Thread.sleep( Delay );

				} // try

				catch( Exception e )
				{
					mw.WriteMessage("Sleep error:: " + e );

				} // catch

			} // while

		} else {

			System.out.println("Unable to register with the event manager.\n\n" );

		} // if

	} // main
	
	protected void halt(){
		Done = true;

		try
		{
			em.UnRegister();

    	} // try

    	catch (Exception e)
    	{
			mw.WriteMessage("Error unregistering: " + e);

    	} // catch

		customHalt();
    	mw.WriteMessage("\n\nSimulation Stopped. \n");
	}
	
	protected abstract void customHalt();
	
	protected abstract void initialPostPhase();
	
	protected abstract void handlePhase();
	
	protected abstract void finalPostPhase();
	
	protected abstract void beforeLooping();

	protected EventManagerInterface register(String args[]) {
		EventManagerInterface em = null;	// Interface object to the event manager

		System.out.println("\n\nAttempting to register on the machine:: " + EvtMgrIP );
		
		try
		{
	 		if ( args.length == 0 )
	 		{
				// event manager is on the local system
				em = new EventManagerInterface(EvtMgrIP);
			} else {

				// event manager is not on the local system
				EvtMgrIP = args[0];

				em = new EventManagerInterface(EvtMgrIP);
 			} // if
		}
		catch (Exception e)
		{
			System.out.println("Error instantiating event manager interface: " + e);
			registered = false;

		} // catch

		return em;
	}
	
	protected void postEvent(int EvtId)
	{
		// Here we create the event.
		Event evt = new Event(EvtId);

		// Here we send the event to the event manager.
		try
		{
			em.SendEvent(evt);
			//mw.WriteMessage( "Sent Humidity Event" );

		} // try

		catch (Exception e)
		{
			System.out.println( "Error Posting Event:: " + e );

		} // catch

	} // postEvent

	protected void postEvent(int EvtId, String EvtMsg)
	{
		// Here we create the event.
		Event evt = new Event(EvtId, EvtMsg);

		// Here we send the event to the event manager.
		try
		{
			em.SendEvent( evt );
			//mw.WriteMessage( "Sent Humidity Event" );

		} // try

		catch (Exception e)
		{
			System.out.println( "Error Posting Event:: " + e );

		} // catch

	} // postEvent
	
	
	private MessageWindow createMessageWindow() {
		MessageWindow mw = new MessageWindow(mwTitle, mwXpos, mwYpos);
		
		return mw;
	}
	
	public boolean isRegistered() {
		return registered;
	}
}

